package com.jin.webvideo.util.sys;


import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.io.UnsupportedEncodingException;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.Security;
import java.security.spec.AlgorithmParameterSpec;
import java.util.Base64;

public class EncryptUtil {
    public static long random(long min, long max){
        return (long) (Math.random()*(max - min) + min);
    }
    public static long timestamp(){
        return System.currentTimeMillis();
    }
    public static byte[] offset(byte[] bs, int offset){
        offset = offset % bs.length;
        int i = 0;
        int l = bs.length;
        byte[] rst = new byte[l];
        while (i < l){
            rst[(i + offset + l) % l] = bs[i];
            i++;
        }
        return rst;
    }
    public static boolean equals(byte[] arr1, byte[] arr2){
        if (arr1.length != arr2.length){
            return false;
        }
        for (int i = 0, l = arr1.length; i < l; i++){
            if (arr1[i] != arr2[i]){
                return false;
            }
        }
        return true;
    }
    public static byte[] base64Encrypt(byte[] bs){
        return Base64.getEncoder().encode(bs);
    }
    public static String base64Encrypt(String data) throws UnsupportedEncodingException {
        return new String(base64Encrypt(data.getBytes(StandardCharsets.UTF_8)) , "utf-8");
    }
    public static byte[] base64Decrypt(byte[] data)  {
        return Base64.getDecoder().decode(data);
    }
    public static String base64Decrypt(String data) throws UnsupportedEncodingException {
        return new String(base64Decrypt(data.getBytes(StandardCharsets.UTF_8)),"utf-8");
    }

    public static byte[] md5(byte[] data) {
        byte[] md5 = new byte[0];
        StringBuilder sb = new StringBuilder();
        try {
            MessageDigest md = MessageDigest.getInstance("md5");
            md5 = md.digest(data);
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        }
        return md5;
    }
    public static String md5Hex(String data) {
        byte[] bs = md5(data.getBytes(StandardCharsets.UTF_8));
        return toHex(bs);
    }

    public static String toHex(byte[] bs){
        StringBuilder stringBuilder = new StringBuilder();
        for (byte b : bs) {
            String part = Integer.toHexString(b & 0xff);
            if (part.length() == 1) {
                part = "0" + part;
            }
            stringBuilder.append(part);
        }
        return stringBuilder.toString();
    }
    public static byte[] toByte(String hex){
        byte[] bs = new byte[hex.length()/2];
        for (int i = 0, l = hex.length()/2; i < l; i++){
            bs[i] = (byte) Integer.parseInt(hex.substring(i*2, i*2 + 2),16);
        }
        return bs;
    }
    public static byte[] toHex(String data){
        char[] chars = data.toCharArray();
        if (1 == chars.length % 2){
            return null;
        }
        byte[] bs = new byte[chars.length/2];
        for (int i = 0; i < chars.length; i += 2) {
            String temp = String.format("%c%c", chars[i], chars[i+1]);
            bs[i/2] = (byte) Integer.parseInt(temp, 16);
        }
        return bs;
    }
    public static byte[] decryptAESCBCPKCS5(byte[] encrypted, byte[] initVector, byte[] key) {
        try {
            Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
            SecretKeySpec keySpec = new SecretKeySpec(key, "AES");
            AlgorithmParameterSpec paramSpec = new IvParameterSpec(initVector);
            cipher.init(Cipher.DECRYPT_MODE, keySpec, paramSpec);
            byte[] bs = cipher.doFinal(encrypted);
            return bs;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return new byte[0];
    }

    public static byte[] encryptAESCBCPKCS5(String encrypted, byte[] initVector, byte[] key) {
        try {
            Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
            SecretKeySpec keySpec = new SecretKeySpec(key, "AES");
            AlgorithmParameterSpec paramSpec = new IvParameterSpec(initVector);
            cipher.init(Cipher.ENCRYPT_MODE, keySpec, paramSpec);
            return cipher.doFinal(encrypted.getBytes(StandardCharsets.UTF_8));
        } catch (Exception e) {
            e.printStackTrace();
        }
        return new byte[0];
    }
}
